/** * Sackmesser (NavajaSuiza) 1.3 - Plantilla varios sensores. AgroalNext25_Plantilla-varios versión 1.3 * Autor : PEDRO ANGEL VAZQUEZ ALIAS. 07/04/2025 * Sensores soportados: * LSE01-LB o SE01-LB * SE0X-LB + Sondas DR-SE-6P * LMS01-LB * SW3L-LB * lsn50v2-s31, lsn50v2-s31B */ // Autor : PEDRO ANGEL VAZQUEZ ALIAS. 07/04/2025 // Sensores disponibles: // función para manejar las solicitudes HTTP POST entrantes. Cuando se recibe una solicitud POST, llama a la función handleRepose y le pasa el objeto de solicitud e. // llamada desde TTN al recibir json del device. function doPost(e){ return handleRepose(e) ; } // Código para crear o obtener una hoja llamada '_Logs' function obtenerLogs(libro) { /** * obtenerLogs(libro) * PV - abr-2m25 * En la celda A1 está el contador de registros que lleva a CEN, * libro : libro actual de la hoja de calculo abierta * Si no existe lo crea y si existe devuelve el contador incrementado en 1. */ const SHEET_NAME_LOG = "_Logs"; const sheet_log = libro.getSheetByName(SHEET_NAME_LOG); // comprobar si hoja existe, y si no la inserta. if (!sheet_log) { libro.insertSheet(SHEET_NAME_LOG); sheet_log = libro.getSheetByName(SHEET_NAME_LOG); } let e_number = 1; // Obtener contador de ejecuciones en celda A1 if (sheet_log.getRange('A1').isBlank()) { sheet_log.getRange('A1').setValue(1); } else { e_number = sheet_log.getRange('A1').getValue() + 1; sheet_log.getRange('A1').setValue(e_number); } return e_number; } // Función para manejar la respuesta function handleRepose(e) { const libro = SpreadsheetApp.getActiveSpreadsheet(); let jsonData = JSON.parse(e.postData.contents); const e_number = obtenerLogs(libro); const tipoSensor = jsonData.uplink_message.version_ids.model_id.toString(); switch (tipoSensor) { case "lse01": const tipofamilia = jsonData.uplink_message.decoded_payload.modelo_sensor !== undefined ? jsonData.uplink_message.decoded_payload.modelo_sensor.toString() : ''; switch (tipofamilia) { case "SE0X-LB": anadirSE0X(jsonData, e_number, libro); break; default: //Declaraciones ejecutadas cuando ninguno de los valores coincide con el valor de la expresión anadirLSE01(jsonData, e_number, libro); break; } // fin switch tipofamilia break; case "llms01": anadirLMS01(jsonData, e_number, libro); break; case "sw3l": anadirSW3L(jsonData, e_number, libro); break; case "lsn50v2-s31": anadirs31b(jsonData, e_number, libro); break; default: //Declaraciones ejecutadas cuando ninguno de los valores coincide con el valor de la expresión break; } } function anadirLSE01 (jsonDatos,cen,libro) { /** * PV - abr2m25 * Añade un elemento en la hoja indicada los datos recibidos de sensores tipo lse01 dragano. * jsonDatos : datos recibidos sensor via TTN * cen : contador de elementos recibidos. Lo coge automáticamente de Logs. * libro : hoja de calculo activa */ // Definir Variables para el manejo del libro y hoja const SHEET_NAME = "Humedad"; const SHEET_NAME_LOG = "_Logs"; // por si falla con try..catch const hojaDatos = libro.getSheetByName(SHEET_NAME); // comprobar si hoja existe, y si no la inserta. if (!hojaDatos) { libro.insertSheet(SHEET_NAME); hojaDatos = libro.getSheetByName(SHEET_NAME); } try{ // Cabecera LSE01 - Humedad // La creamos si no existe if(hojaDatos.getRange('A1').isBlank()){ let h_row = []; //contenedor para almacenar con push los nombres de las cabeceras h_row.push("cen"); // current execution number h_row.push("fecha-hora"); h_row.push("Ubicacion"); h_row.push("Humedad % Suelo"); h_row.push("Temperatura ºC Suelo"); h_row.push("Conductividad Suelo"); h_row.push("Bateria"); h_row.push("Temperatura ºC Aire"); hojaDatos.getRange(1, 1, 1, h_row.length).setValues([h_row]); } // Parseamos los datos entrantes, que vienen en formato JSON // let jsonDatos = JSON.parse(e.postData.contents); let row = []; row.push(cen); row.push(new Date()); row.push(jsonDatos.end_device_ids.device_id); row.push(jsonDatos.uplink_message.decoded_payload.water_SOIL !== undefined ? jsonDatos.uplink_message.decoded_payload.water_SOIL.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.temp_SOIL !== undefined ? jsonDatos.uplink_message.decoded_payload.temp_SOIL.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.conduct_SOIL !== undefined ? jsonDatos.uplink_message.decoded_payload.conduct_SOIL.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.Bat !== undefined ? jsonDatos.uplink_message.decoded_payload.Bat.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.TempC_DS18B20 !== undefined ? jsonDatos.uplink_message.decoded_payload.TempC_DS18B20.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.version_ids.model_id !== undefined ? jsonDatos.uplink_message.version_ids.model_id.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.Mod !== undefined ? jsonDatos.uplink_message.decoded_payload.Mod.toString().replace('.', ',') : ''); hojaDatos.appendRow(row); } catch (err) { // Guardamos los errores que haya podido haber const sheet_log = libro.getSheetByName(SHEET_NAME_LOG); sheet_log.appendRow([cen, new Date(), err.message]); } } function anadirSE0X (jsonDatos,cen,libro) { /** * PV - abr2m25 * Añade un elemento en la hoja indicada los datos recibidos de sensores tipo lse0x dragano, con sondas DR-SE-6P * jsonDatos : datos recibidos sensor via TTN * cen : contador de elementos recibidos. Lo coge automáticamente de Logs. * libro : hoja de calculo activa * * Este sensor se añadirá como un SE01, cargar el payload del SE0X-LB de Github, y modificarlo * añadiendo linea con * --> data.modelo_sensor= "SE0X-LB"; // PedroVazquez - abr2m25 - Añadir campo indicador de sensor SE0X-LB */ // Definir Variables para el manejo del libro y hoja const SHEET_NAME = "Humedad"; const SHEET_NAME_LOG = "_Logs"; // por si falla con try..catch const hojaDatos = libro.getSheetByName(SHEET_NAME); // comprobar si hoja existe, y si no la inserta. if (!hojaDatos) { libro.insertSheet(SHEET_NAME); hojaDatos = libro.getSheetByName(SHEET_NAME); } try{ // Cabecera LSE01 - Humedad // La creamos si no existe if(hojaDatos.getRange('A1').isBlank()){ let h_row = []; //contenedor para almacenar con push los nombres de las cabeceras h_row.push("cen"); // current execution number h_row.push("fecha-hora"); h_row.push("Ubicacion"); h_row.push("Humedad % Suelo"); h_row.push("Temperatura ºC Suelo"); h_row.push("Conductividad Suelo"); h_row.push("Bateria"); h_row.push("Temperatura ºC Aire"); hojaDatos.getRange(1, 1, 1, h_row.length).setValues([h_row]); } // Parseamos los datos entrantes, que vienen en formato JSON // let jsonDatos = JSON.parse(e.postData.contents); // el sensor puede tener hasta 4 sondas const s_flag = jsonDatos.uplink_message.decoded_payload.s_flag !== undefined ? jsonDatos.uplink_message.decoded_payload.s_flag.toString() : ''; let sondas; switch (s_flag) { case "1000": sondas = 1; break; case "1100" : sondas = 2; break; case "1110" : sondas = 3; break; case "1111" : sondas = 4; break; default: //Declaraciones ejecutadas cuando ninguno de los valores coincide con el valor de la expresión sondas = 0; break; } for (let sonda = 1; sonda <= sondas; sonda++) { let humedad = "water_SOIL"+ sonda.toString(); let temperatura = "temp_SOIL" + sonda.toString(); let conductividad = "conduct_SOIL" + sonda.toString(); let row = []; row.push(cen); row.push(new Date()); row.push(jsonDatos.end_device_ids.device_id + "(" + sonda.toString() + ")"); row.push(jsonDatos.uplink_message.decoded_payload[humedad] !== undefined ? jsonDatos.uplink_message.decoded_payload[humedad].toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload[temperatura] !== undefined ? jsonDatos.uplink_message.decoded_payload[temperatura].toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload[conductividad] !== undefined ? jsonDatos.uplink_message.decoded_payload[conductividad].toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.BatV !== undefined ? jsonDatos.uplink_message.decoded_payload.BatV.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.TempC_DS18B20 !== undefined ? jsonDatos.uplink_message.decoded_payload.TempC_DS18B20.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.modelo_sensor !== undefined ? jsonDatos.uplink_message.decoded_payload.modelo_sensor.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.Mod !== undefined ? jsonDatos.uplink_message.decoded_payload.Mod.toString().replace('.', ',') : ''); hojaDatos.appendRow(row); } } catch (err) { // Guardamos los errores que haya podido haber const sheet_log = libro.getSheetByName(SHEET_NAME_LOG); sheet_log.appendRow([cen, new Date(), err.message]); } } function anadirs31b (jsonDatos,cen,libro) { /** * PV - abr2m25 * Añade un elemento en la hoja indicada los datos recibidos de sensores tipo lse01 dragano. * jsonDatos : datos recibidos sensor via TTN * cen : contador de elementos recibidos. Lo coge automáticamente de Logs. * libro : hoja de calculo activa * "ADC_CH0V": 5.557, "BatV": 3.606, "Digital_IStatus": "L", "Door_status": "OPEN", "EXTI_Trigger": "FALSE", "Hum_SHT": 48.9, "TempC1": 2661.3, "TempC_SHT": 26.1, "Work_mode": "IIC" */ // Definir Variables para el manejo del libro y hoja const SHEET_NAME = "Humedad Ambiente"; const SHEET_NAME_LOG = "_Logs"; // por si falla con try..catch const hojaDatos = libro.getSheetByName(SHEET_NAME); // comprobar si hoja existe, y si no la inserta. if (!hojaDatos) { libro.insertSheet(SHEET_NAME); hojaDatos = libro.getSheetByName(SHEET_NAME); } try{ // Cabecera LSE01 - Humedad // La creamos si no existe if(hojaDatos.getRange('A1').isBlank()){ let h_row = []; //contenedor para almacenar con push los nombres de las cabeceras h_row.push("cen"); // current execution number h_row.push("fecha-hora"); h_row.push("Ubicacion"); h_row.push("Humedad"); h_row.push("Temperatura ºC SHT "); h_row.push("Temperatura ºC C1"); h_row.push("Bateria"); h_row.push("Modelo"); h_row.push("Modo"); hojaDatos.getRange(1, 1, 1, h_row.length).setValues([h_row]); } // Parseamos los datos entrantes, que vienen en formato JSON // let jsonDatos = JSON.parse(e.postData.contents); let row = []; row.push(cen); row.push(new Date()); row.push(jsonDatos.end_device_ids.device_id); row.push(jsonDatos.uplink_message.decoded_payload.Hum_SHT !== undefined ? jsonDatos.uplink_message.decoded_payload.Hum_SHT.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.TempC_SHT !== undefined ? jsonDatos.uplink_message.decoded_payload.TempC_SHT.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.TempC1 !== undefined ? jsonDatos.uplink_message.decoded_payload.TempC1.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.BatV !== undefined ? jsonDatos.uplink_message.decoded_payload.BatV.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.version_ids.model_id !== undefined ? jsonDatos.uplink_message.version_ids.model_id.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.Work_mode !== undefined ? jsonDatos.uplink_message.decoded_payload.Work_mode.toString().replace('.', ',') : ''); hojaDatos.appendRow(row); } catch (err) { // Guardamos los errores que haya podido haber const sheet_log = libro.getSheetByName(SHEET_NAME_LOG); sheet_log.appendRow([cen, new Date(), err.message]); } } function anadirLMS01 (jsonDatos, cen, libro) { /** * PV - abr2m25 * Añade un elemento en la hoja indicada los datos recibidos de sensores tipo MLS01 dragano. * jsonDatos : datos recibidos sensor via TTN * cen : contador de elementos recibidos. Lo coge automáticamente de Logs. * libro : hoja de calculo activa */ // Definir Variables para el manejo del libro y hoja const SHEET_NAME = "Humectacion"; const SHEET_NAME_LOG = "_Logs"; // por si falla con try..catch const hojaDatos = libro.getSheetByName(SHEET_NAME); // comprobar si hoja existe, y si no la inserta. if (!hojaDatos) { libro.insertSheet(SHEET_NAME); hojaDatos = libro.getSheetByName(SHEET_NAME); } try{ // Cabecera LMS01 - Humectación en Hoja // La creamos si no existe if(hojaDatos.getRange('A1').isBlank()){ let h_row = []; //contenedor para almacenar con push los nombres de las cabeceras h_row.push("cen"); // current execution number h_row.push("fecha-hora"); h_row.push("Ubicacion"); h_row.push("Humedad"); h_row.push("Temperatura ºC"); h_row.push("Bateria"); h_row.push("Temperatura ºC Aire"); hojaDatos.getRange(1, 1, 1, h_row.length).setValues([h_row]); } // Parseamos los datos entrantes, que vienen en formato JSON let row = []; row.push(cen); row.push(new Date()); row.push(jsonDatos.end_device_ids.device_id); row.push(jsonDatos.uplink_message.decoded_payload.Leaf_Moisture !== undefined ? jsonDatos.uplink_message.decoded_payload.Leaf_Moisture.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.Leaf_Temperature !== undefined ? jsonDatos.uplink_message.decoded_payload.Leaf_Temperature.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.Bat !== undefined ? jsonDatos.uplink_message.decoded_payload.Bat.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.decoded_payload.TempC_DS18B20 !== undefined ? jsonDatos.uplink_message.decoded_payload.TempC_DS18B20.toString().replace('.', ',') : ''); row.push(jsonDatos.uplink_message.version_ids.model_id !== undefined ? jsonDatos.uplink_message.version_ids.model_id.toString().replace('.', ',') : ''); hojaDatos.appendRow(row); } catch (err) { // Guardamos los errores que haya podido haber const sheet_log = libro.getSheetByName(SHEET_NAME_LOG); sheet_log.appendRow([cen, new Date(), err.message]); } } function anadirSW3L (jsonDatos, cen, libro) { /** * PV - abr2m25 * Añade un elemento en la hoja indicada los datos recibidos de sensores tipo SW3L-LB dragino. * jsonDatos : datos recibidos sensor via TTN * cen : contador de elementos recibidos. Lo coge automáticamente de Logs. * libro : hoja de calculo activa */ // Definir Variables para el manejo del libro y hoja const SHEET_NAME = "Contador"; const SHEET_NAME_LOG = "_Logs"; // por si falla con try..catch const hojaDatos = libro.getSheetByName(SHEET_NAME); // comprobar si hoja existe, y si no la inserta. if (!hojaDatos) { libro.insertSheet(SHEET_NAME); hojaDatos = libro.getSheetByName(SHEET_NAME); } try{ // Cabecera LMS01 - Humectación en Hoja // La creamos si no existe if(hojaDatos.getRange('A1').isBlank()){ let h_row = []; //contenedor para almacenar con push los nombres de las cabeceras h_row.push("cen"); // current execution number h_row.push("fecha-hora"); h_row.push("nombre"); h_row.push("pulsos"); h_row.push("litros"); h_row.push("alarma"); hojaDatos.getRange(1, 1, 1, h_row.length).setValues([h_row]); } // Parseamos los datos entrantes, que vienen en formato JSON let row = []; row.push(cen); row.push(new Date()); row.push(jsonDatos.end_device_ids.device_id); //row.push(jsonDatos.uplink_message.decoded_payload.Last_pulse !== undefined ? jsonDatos.uplink_message.decoded_payload.Last_pulse : ''); row.push(jsonDatos.uplink_message.decoded_payload.Total_pulse !== undefined ? jsonDatos.uplink_message.decoded_payload.Total_pulse : ''); row.push(jsonDatos.uplink_message.decoded_payload.Water_flow_value !== undefined ? jsonDatos.uplink_message.decoded_payload.Water_flow_value : ''); row.push(jsonDatos.uplink_message.decoded_payload.Alarm); row.push(jsonDatos.uplink_message.version_ids.model_id !== undefined ? jsonDatos.uplink_message.version_ids.model_id.toString().replace('.', ',') : ''); /* "uplink_message": { "session_key_id": "AZX7FpZwLwE1d8+yYFgdAQ==", "f_port": 2, "f_cnt": 1, "frm_payload": "AQAAAAAAAWfuW9o=", "decoded_payload": { "Alarm": "FALSE", "Calculate_flag": 0, "Data_time": "2025-04-03 09:58:50", "MOD": 0, "Total_pulse": 0, "Water_flow_value": 0 }, */ hojaDatos.appendRow(row); } catch (err) { // Guardamos los errores que haya podido haber const sheet_log = libro.getSheetByName(SHEET_NAME_LOG); sheet_log.appendRow([cen, new Date(), err.message]); } }